#include "mstl.h"
#include <stdarg.h>

IFDEBUG(int dbgvars[16];)

#ifndef __WIN__
void *_aligned_malloc(size_t size, size_t alignment) {
	void *ptr;
	int err = posix_memalign(&ptr,alignment,size); //todo generate exception
	return err? 0 : ptr;
}
void _aligned_free(void *ptr) {
	free(ptr);
}
#endif
#ifdef MALLOC_COUNT
struct MCount mcounts={0,0,0};
#endif

#ifdef TRACE_IN_MEMORY
dbg_lines_struct dbg_lines[16];
int dbg_li;
#endif

#if defined(MALLOC_FREE_TEST) || defined(MALLOC_COUNT) || defined(MALLOC_BOUNDARY_TEST)

void *mstl_alloc( size_t s)
{ 
	_ASSERT(s>=0);
#ifdef MALLOC_COUNT
  mcounts.variable++;
#endif
#if defined(MALLOC_FREE_TEST) || defined(MALLOC_BOUNDARY_TEST)
  char *p=(char *)malloc(s+12);
  //mymalloccheck(p,s);
  //mymemcheck();
	_ASSERT(p);
  *(int *)p=s+8;
  *(int *)(p+4)=0xa110cced;
  *(int *)(p+s+8)=0xabbadeff;
  //printf("r(%p,%d)",p+8,s);
#ifdef MALLOC_WIPE
  memset(p+8, 0x33, s );
#endif
//TRACEP(p,p)
  return p+8;
#else
  void *p=malloc(s);
#ifdef MALLOC_WIPE
    memset(p, 0x33, s );
#endif
  return p;
#endif
}

void mstl_free( void *p)
{
#ifdef MALLOC_COUNT
  mcounts.variable--;
#endif
#if defined(MALLOC_FREE_TEST) || defined(MALLOC_BOUNDARY_TEST)
  char *q=(char*)p-8;
  //printf("{1,%p},",p);
  if (*(int *)(q+4)!=0xa110cced || *(int *)( q + *(int *)q )!=0xabbadeff ) { printf("Corruption on %p, size=%d, border={%x,%x}!!!\n",p,*(int *)q-8,*(int *)(q+4),*(int *)( q + *(int *)q)); _ASSERT(0); }
  else
  {
    *(int *)(q+4)=0xdecea5ed;
    *(int *)( q + *(int *)q )=0xdeadabba;
#ifdef MALLOC_WIPE
    memset(p, 0x55, *(int *)q - 8 );
#endif
//  myfree(q,4+*(int *)q);
    free(q);
  }
#else
  free(p);
#endif
}

#endif

/*
#define FLL 32
struct{void *ptr; int len;} freelist[FLL];
int freelisti=0, freelistcount=0;

void mymalloccheck(void *mallo,int len)
{
  for(int i=len>>2;--i>=0;)
  { _ASSERT(((int *)mallo)[i]!=0x33333333);
  }
}
void mymemcheck()
{
  if(freelistcount==FLL)
  { for(int i=FLL;--i>=0;)
    { if( *(int *)(freelist[i].ptr)!=0x33333333 ) DIV_BY_ZERO(freelist[i].ptr)
    }
  }
}

void myfree(void *ptr, int len)
{ 
  //if (len!=24) { free(ptr); return; }
  if(freelistcount==FLL)
  { mymemcheck();
    //char *p=(char *)freelist[freelisti].ptr;
    //for(int j=freelist[freelisti].len;--j>=0;)
    //{ if(p[j]!=0x33){DIV_BY_ZERO(freelist[freelisti].len) }
    //}
    memset(freelist[freelisti].ptr,0x44,8);
    free(freelist[freelisti].ptr);
  }
  else freelistcount++;
  freelist[freelisti].ptr=ptr;
  freelist[freelisti].len=len;
  freelisti=(freelisti+1)%FLL;
  memset(ptr,0x33,8);
  //memset(ptr,0x33,len);
}
*/
namespace MSTL
{

#ifdef UNITALLOCATOR_ASSURESINGLETHREAD_TEST
int MEM_SEMA=0;
#endif

int DynamicDuplicable::sizeOf() const { _ASSERT(0); return 0; }
void DynamicDuplicable::duplicateIn(void *space) const { _ASSERT(0); }
DynamicDuplicable::~DynamicDuplicable() {}

String String::create(int buf, const char *format,...)
{ 
  String b(buf);
  va_list va; va_start(va, format); vsprintf((char *)b, format, va); va_end(va);
  return (char *)b;
}

String String::subset(int pos, int len) 
{ String s(len); 
  memcpy((char *)s, ((char *)(*this))+pos, len); 
  return s; 
} 

int String::strcmp(const String &b) const
{ int i = memcmp((char *)*this,(char *)b,length()<b.length()?length():b.length()); 
	return i==0 ? ( length()>b.length() ? 1 : ( length()==b.length() ? 0 : -1 ) ) : i; 
}

}
